package com.hqbzl.chat;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

import com.hqbzl.chat.handler.HeartBeatHandler;
import com.hqbzl.chat.handler.PingMessageRequestHandler;
import com.hqbzl.chat.handler.PingMessageResponseHandler;
import com.hqbzl.chat.handler.RpcResponseHandler;
import com.hqbzl.chat.message.RpcRequestMessage;
import com.hqbzl.chat.message.RpcResponseMessage;
import com.hqbzl.chat.protocol.MessageCodec;
import com.hqbzl.chat.protocol.ProcotolFramDecoder;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RpcClient {
    public static final LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
    public static final MessageCodec MESSAGE_CODEC = new MessageCodec();
    // static ThreadLocal<Boolean> LOGIN_RESULT = new ThreadLocal<Boolean>();
    static AtomicBoolean LOGIN_RESULT = new AtomicBoolean(false);

    public static void main(String[] args) {
        CountDownLatch LOGIN_CDT = new CountDownLatch(1);
        final NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            final Bootstrap bootstrap = new Bootstrap();
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.group(group);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(LOGGING_HANDLER);
                    ch.pipeline().addLast(new ProcotolFramDecoder());
                    ch.pipeline().addLast(MESSAGE_CODEC);
                    ch.pipeline().addLast(new RpcResponseHandler());
                    // 写空闲比服务器要小
                    ch.pipeline().addLast(new IdleStateHandler(0, 3, 0));
                    // 即可以同时作为入栈和出栈处理器
                    ch.pipeline().addLast(new HeartBeatHandler());
                    ch.pipeline().addLast(new PingMessageResponseHandler());
                    ch.pipeline().addLast("clientHandler", new ChannelInboundHandlerAdapter() {
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            final RpcRequestMessage build = RpcRequestMessage.builder()
                                    .interfaceName("com.hqbzl.chat.service.impl.UserServiceImpl")
                                    .methodName("say")
                                    .parameterTypes(new Class[]{String.class, String.class})
                                    .parameterValus(new Object[]{"1", "2"})
                                    .build();
                            ctx.writeAndFlush(build);
                            log.debug("wait");
                              /*
                              new Thread(() -> {}, "system-in").start();
                             */
                        }

                        @Override
                        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                            log.debug("channelRead: {}", msg);
                            if (msg instanceof RpcResponseMessage) {

                            }
                            LOGIN_CDT.countDown();
                            super.channelRead(ctx, msg);
                        }
                    });
                }
            });
            final Channel channel = bootstrap.connect("localhost", 7788).sync().channel();
            // 连接创建好
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();

        } finally {
            group.shutdownGracefully();
        }
    }

}
